﻿using System;
using System.Collections.Generic;
using System.ServiceModel;
using XchangeStreamer.Utilities;
using System.Linq;
using XchangeStreamer.Core;

namespace XchangeStreamer.CacheServer.Core
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple, Namespace = Settings.Namespace)]
    internal sealed partial class Engine : IDisposable
    {
        #region Private Fields

        private System.Threading.ReaderWriterLockSlim sync;
        private List<System.ServiceModel.Channels.Message> messages = new List<System.ServiceModel.Channels.Message>();

        #endregion

        #region Const.

        public Engine()
        {
            this.sync = Synchronizer.GetSynchronizerInstance(System.Threading.LockRecursionPolicy.NoRecursion);
        }

        #endregion

        #region Private Methods

        private int messageId = 0;
        //private int topicId = 0;
        private void Add(System.ServiceModel.Channels.Message message)
        {
            using (new WritableSynchronizer(this.sync, LockType.ReaderWriterLockSlim))
            {
                this.messages.Add(message);

                var msgId = int.Parse(message.Headers.MessageId.ToString());
                //var topId = message.Headers.GetHeader<int>(1);

                //if (this.messageId > msgId)
                //{
                //    Console.WriteLine("Unordered Message");   
                //}
                this.messageId = msgId;
                //this.topicId = topId;
            }
        }

        private List<System.ServiceModel.Channels.Message> Get(int clientMessageId, int serverMessageId, int[] topicsId)
        {
            using (new ReadOnlySynchronizer(this.sync, LockType.ReaderWriterLockSlim))
            {
                var messages = from message in this.messages.AsParallel()
                               where topicsId.Contains(message.Headers.GetHeader<int>(1)) == true &&
                                int.Parse(message.Headers.MessageId.ToString()) > clientMessageId &&
                                int.Parse(message.Headers.MessageId.ToString()) < serverMessageId
                               select message;

                return messages.ToList();
            }
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            this.sync.Dispose();
            this.sync = null;
            this.messages.Clear();
            this.messages = null;
        }

        #endregion
    }
}
